using Unity.Collections;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class VForwardLights
{
    static class LightConstantBuffer
    {
        public static int
            _MainLightPosition; // DeferredLights.LightConstantBuffer also refers to the same ShaderPropertyID - TODO: move this definition to a common location shared by other UniversalRP classes

        public static int
            _MainLightColor; // DeferredLights.LightConstantBuffer also refers to the same ShaderPropertyID - TODO: move this definition to a common location shared by other UniversalRP classes
        public static int _AdditionalLightsCount;
        public static int _AdditionalLightsPosition;
        public static int _AdditionalLightsColor;
        
      
    }
    Vector4[] m_AdditionalLightPositions;
    Vector4[] m_AdditionalLightColors;
    internal VForwardLights()
    {//_VMainLightDirection
        LightConstantBuffer._MainLightPosition = Shader.PropertyToID("_VMainLightDirection");
        LightConstantBuffer._MainLightColor = Shader.PropertyToID("_VMainLightColor");
        LightConstantBuffer._AdditionalLightsCount = Shader.PropertyToID("_AdditionalLightsCount");
        
        LightConstantBuffer._AdditionalLightsPosition = Shader.PropertyToID("_AdditionalLightsPosition");
        LightConstantBuffer._AdditionalLightsColor = Shader.PropertyToID("_AdditionalLightsColor");
        int maxLights = VUniversalRenderPipeline.maxVisibleAdditionalLights;
        m_AdditionalLightPositions = new Vector4[maxLights];
        m_AdditionalLightColors = new Vector4[maxLights];
        
    }
    //只要Setup正确即可 传入cull后的data
    public void Setup(ScriptableRenderContext context, ref VRenderingData renderingData)
    {
        CommandBuffer cmd = CommandBufferPool.Get();
        SetupShaderLightConstants(cmd, ref renderingData);
        context.ExecuteCommandBuffer(cmd);
        CommandBufferPool.Release(cmd);
    }
    void SetupShaderLightConstants(CommandBuffer cmd, ref VRenderingData renderingData)
    {
        SetupMainLightConstants(cmd, ref renderingData.lightData);
        SetupAdditionalLightConstants(cmd, ref renderingData);
    }
    void SetupMainLightConstants(CommandBuffer cmd, ref VLightData lightData)
    {
        Vector4 lightPos, lightColor;
        InitializeLightConstants(lightData.visibleLights,0,out lightPos,out lightColor);
        
        cmd.SetGlobalVector(LightConstantBuffer._MainLightPosition, lightPos);
        cmd.SetGlobalVector(LightConstantBuffer._MainLightColor, lightColor);
       
    }

    void SetupAdditionalLightConstants(CommandBuffer cmd, ref VRenderingData renderingData)
    {
        ref VLightData lightData = ref renderingData.lightData;
        var cullResults = renderingData.cullResults;
        var lights = lightData.visibleLights;
        int maxVisibleAdditionalLights = VUniversalRenderPipeline.maxVisibleAdditionalLights;
        int additionalLightsCount = SetupPerObjectLightIndices(cullResults, ref lightData);
        if (additionalLightsCount > 0)
        {
            for (int i = 0, lightIter = 0; i < lights.Length&& lightIter < maxVisibleAdditionalLights; i++)
            {
                if (lightData.mainLightIndex != i)
                {
                    VisibleLight light = lights[i];
                    InitializeLightConstants(lights, i, out m_AdditionalLightPositions[lightIter],
                        out m_AdditionalLightColors[lightIter]
                        );
                    lightIter++;
                }
            }
        }
        cmd.SetGlobalVectorArray(LightConstantBuffer._AdditionalLightsPosition, m_AdditionalLightPositions);
        cmd.SetGlobalVectorArray(LightConstantBuffer._AdditionalLightsColor, m_AdditionalLightColors);
        cmd.SetGlobalVector(LightConstantBuffer._AdditionalLightsCount, new Vector4(lightData.additionalLightsCount,
            0.0f, 0.0f, 0.0f));
    }
    void InitializeLightConstants(NativeArray<VisibleLight> lights , int lightIndex, out Vector4 lightPos, out Vector4 lightColor)
    {
        
        VisibleLight lightData = lights[lightIndex];
        if (lightData.lightType == LightType.Directional)
        {
            
            Vector4 dir = -lightData.localToWorldMatrix.GetColumn(2);
            lightPos = new Vector4(dir.x, dir.y, dir.z, 0.0f);
        }
        else
        {
            Vector4 pos = lightData.localToWorldMatrix.GetColumn(3);
            lightPos = new Vector4(pos.x, pos.y, pos.z,1);
        }
        // VisibleLight.finalColor already returns color in active color space
        lightColor = lightData.finalColor;
    }

    int SetupPerObjectLightIndices(CullingResults cullResults, ref VLightData lightData)
    {
        if (lightData.additionalLightsCount == 0)
            return lightData.additionalLightsCount;

        var visibleLights = lightData.visibleLights;
        int additionalLightsCount = 0;
        for (int i = 0; i < visibleLights.Length; ++i)
        {
            if (additionalLightsCount >= VUniversalRenderPipeline.maxVisibleAdditionalLights)
                break;

            VisibleLight light = visibleLights[i];
            if (i == lightData.mainLightIndex)
            {
                continue;
            }
            else
            {
                ++additionalLightsCount;
            }
        }


        return additionalLightsCount;
    }





}